package com.springleaf.arena.display
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * The arena class contains all the UI data about the Arena and it's childrens.
	 * It's also the main event dispatcher for all the interactive events. You should
	 * totally use this class if you don't want to use the Engine (but be warned).
	 * 
	 * How to use:
	 * 1. Create Grid
	 * 2. Create Grid Cell
	 * 3. Draw
	 * 3.1. Draw Background (optional)
	 * 3.2. Draw Foreground (optional)
	 * 4. Update
	 * 
	 * This class manipulates the grid, background, foreground and displayable objects.
	 */
	public class UIArena extends Sprite
	{
		private var grid:UIGrid;
		private var displayableObjects:Array;
		
		private var ignoreBackground:Boolean;
		
		private var _backgroundBitmap:Bitmap;
		private var _backgroundCanvas:BitmapData;
		private var _backgroundSheet:BitmapData;
		private var _backgroundDefaultSize:Rectangle;
		
		private var _foregroundBitmap:Bitmap;
		private var _foregroundCanvas:BitmapData;
		private var _foregroundSheet:BitmapData;
		private var _foregroundDefaultSize:Rectangle;
		
		/**
		 * The ignoreBackground is used for getting the width & height of the entire sprite
		 * with all it's background and foreground or just the grid. (If set to true, it
		 * will also take in consideration the character's extra width and height.
		 */
		public function UIArena(ignoreBackground:Boolean = true) {
			displayableObjects = new Array();
			this.ignoreBackground = ignoreBackground;
		}
		
		////////////////////////////////////////////////////////////////////
		//////////////////////// GRID RELATED METHODS //////////////////////
		////////////////////////////////////////////////////////////////////
		
		/**
		 * Make sure you created the grid and gridCells first by calling the createGrid()
		 * and createGridCell() methods.
		 */
		public function drawGrid():void {
			if (grid) {
				grid.draw();
				grid.x = grid.width / 2;
				grid.y = (grid.cellDefaultSize ? grid.cellDefaultSize.height : 0);
				
				if (_foregroundBitmap) {
					addChildAt(grid, getChildIndex(_foregroundBitmap));
				} else if (_backgroundBitmap) {
					addChildAt(grid, getChildIndex(_backgroundBitmap) + 1);
				} else {
					addChild(grid);
				}
			}
		}
		
		public function createGrid(rows:int, columns:int):void {
			if (grid) {
				destroyGrid();
			}
			grid = new UIGrid(rows, columns);
		}
		
		/**
		 * Make sure you create the grid first by calling the createGrid() method.
		 */
		public function createGridCell(cellSheet:BitmapData, cellDefaultSize:Rectangle, 
									   cellIdleStates:Array):void {
			if (grid) {
				grid.cellSheet = cellSheet;
				grid.cellDefaultSize = cellDefaultSize;
				grid.cellIdleStates = cellIdleStates;
			}
		}
		
		public function destroyGrid():void {
			//TODO (recycle)
		}
		
		////////////////////////////////////////////////////////////////////
		/////////// BACKGROUND AND FOREGROUND RELATED METHODS //////////////
		////////////////////////////////////////////////////////////////////
		
		/**
		 * The xDecalation and yDecalation are used when the background isn't at the same
		 * position as the grid. xDecalation is considered the x position difference
		 * between grid.x and background.x, the same applies to yDecalation. 
		 */
		public function drawBackground(xDecalation:int = 0, yDecalation:int = 0):void {
			if (_backgroundSheet && _backgroundDefaultSize) {
				if (!_backgroundBitmap) {
					_backgroundCanvas = new BitmapData(_backgroundDefaultSize.width, _backgroundDefaultSize.height);
					_backgroundBitmap = new Bitmap(_backgroundCanvas);
					
					_backgroundCanvas.copyPixels(_backgroundSheet, _backgroundDefaultSize, new Point());
					_backgroundBitmap.x = (grid ? grid.x : 0) + xDecalation;
					_backgroundBitmap.y = (grid ? grid.y : 0) + yDecalation;
					addChildAt(_backgroundBitmap, 0);
				}
			}
		}
		
		public function updateBackground():void {
			//TODO
		}
		
		public function removeBackground():void {
			//TODO
		}
		//TODO THINK OF A WAY TO ELIMINATE XPOSITION AND YPOSITION
		/**
		 * The xDecalation and yDecalation are used when the foreground isn't at the same
		 * position as the background. xDecalation is considered the x position difference
		 * between background.x and foreground.x, the same applies to yDecalation.
		 */
		public function drawForeground(xDecalation:int = 0, yDecalation:int = 0):void {
			if (_foregroundSheet && _foregroundDefaultSize) {
				if (!_foregroundBitmap) {
					_foregroundCanvas = new BitmapData(_foregroundDefaultSize.width, _foregroundDefaultSize.height);
					_foregroundBitmap = new Bitmap(_foregroundCanvas);
					
					_foregroundCanvas.copyPixels(_foregroundSheet, _foregroundDefaultSize, new Point());
					_foregroundBitmap.x = (_backgroundBitmap ? _backgroundBitmap.x : 0) + xDecalation;
					_foregroundBitmap.y = (_backgroundBitmap ? _backgroundBitmap.y : 0) + yDecalation;
					
					if (grid) {
						addChildAt(_foregroundBitmap, getChildIndex(grid) + 1);
					} else if (_backgroundBitmap) {
						addChildAt(_foregroundBitmap, getChildIndex(_backgroundBitmap) + 1);
					} else {
						addChild(_foregroundBitmap);
					}
				}
			}
		}
		
		public function updateForeground():void {
			//TODO
		}
		
		public function removeForeground():void {
			//TODO
		}
		
		////////////////////////////////////////////////////////////////////
		////////////// DISPLAYABLE OBJECTS RELATED METHODS /////////////////
		////////////////////////////////////////////////////////////////////
		
		public function updateAnimation():void {
			//TODO
		}
		
		//TODO ADD THE ITEM IN THE updatable LIST IF NEEDED
		public function addDisplayableObject(display:UIDisplayableObject, xPosition:int, 
											 yPosition:int):void {
			display.x = grid.getCellAt(xPosition, yPosition).xPosition + display.xDecalation;
			display.y = grid.getCellAt(xPosition, yPosition).yPosition + display.yDecalation;
			display.value = 3 * (xPosition + yPosition) + 1; 
			
			//TODO CHANGE ME WITH BINARY SEARCH
			//TODO CREATE A METHOD WITH JUST THIS
			//TODO USE A POLL
			if (displayableObjects.length == 0) {
				displayableObjects[0] = display;
				addChildAt(display, numChildren);
			} else {
				for (var i:int = 0; i < displayableObjects.length; i++) {
					if (display.value < displayableObjects[i].value) {
						addChildAt(display, getChildIndex(displayableObjects[i]));
						displayableObjects.splice(i, 0, display);
						return;
					}
				}
				addChild(display);
				displayableObjects[displayableObjects.length] = display;
			}
		}
		
		public function removeDisplayableObject():void {
			//TODO (use a poll)
		}
		
		////////////////////////////////////////////////////////////////////
		///////////////////// SQUARE RELATED METHODS ///////////////////////
		////////////////////////////////////////////////////////////////////
		
		public function disableSquareInteraction():void {
			//TODO take in consideration mouse position
		}
		
		public function enableSquareInteraction():void {
			//TODO take in consideration mouse position
		}
		
		////////////////////////////////////////////////////////////////////
		//////////////////////// SETTERS AND GETTERS ///////////////////////
		////////////////////////////////////////////////////////////////////
		
		public override function get width():Number {
			return (ignoreBackground ? grid.width : this.width);
		}
		
		public override function get height():Number {
			return (ignoreBackground ? grid.height : this.height);
		}
		
		public function get backgroundSheet():BitmapData
		{
			return _backgroundSheet;
		}
		
		public function set backgroundSheet(value:BitmapData):void
		{
			_backgroundSheet = value;
		}

		public function get backgroundDefaultSize():Rectangle
		{
			return _backgroundDefaultSize;
		}

		public function set backgroundDefaultSize(value:Rectangle):void
		{
			_backgroundDefaultSize = value;
		}

		public function get foregroundBitmap():Bitmap
		{
			return _foregroundBitmap;
		}

		public function set foregroundBitmap(value:Bitmap):void
		{
			_foregroundBitmap = value;
		}

		public function get foregroundCanvas():BitmapData
		{
			return _foregroundCanvas;
		}

		public function set foregroundCanvas(value:BitmapData):void
		{
			_foregroundCanvas = value;
		}

		public function get foregroundSheet():BitmapData
		{
			return _foregroundSheet;
		}

		public function set foregroundSheet(value:BitmapData):void
		{
			_foregroundSheet = value;
		}

		public function get foregroundDefaultSize():Rectangle
		{
			return _foregroundDefaultSize;
		}

		public function set foregroundDefaultSize(value:Rectangle):void
		{
			_foregroundDefaultSize = value;
		}


	}
}